﻿using NHibernate.Mapping.ByCode.Conformist;
using NHibernate.Mapping.ByCode;
using NHibernate;
using OnTheWay;
using System.Reflection;
using NHibernate.Type;
using System;
using OnTheWay.Models;
using Models;

namespace BlackMofo.DAL.Mappers
{
    public class ExhibitMapper : DataBaseMapper<Exhibit> { }
    public class ExhibitTypeMapper : DataBaseMapper<ExhibitType> { }
    public class ExhibitUnitMapper : DataBaseMapper<ExhibitUnit> { }
    public class SysAdminMapper : DataBaseMapper<SysAdmin> { }
    public class UserMapper : DataBaseMapper<User> { }

    //internal class Holder
    //{
    //    //Type type;
    //    Object model;
    //    PropertyInfo proerty;

    //    public static Holder InHolder = new Holder();

    //    private void binding(Object model, PropertyInfo proerty)
    //    {
    //        this.model = model;
    //        this.proerty = proerty;
    //    }

    //    //public Object Property 
    //    //{ 
    //    //    get
    //    //    {
    //    //        return type.InvokeMember(proerty.Name, BindingFlags.GetProperty, null, model, null);
    //    //    } 
    //    //}
    //}

    public class DataBaseMapper<T> : BaseMapper<T> where T : Model
    {
        public DataBaseMapper()
        {
            //table
            this.Table("t" + typeof(T).Name);

            if (typeof(T).IsDefined(typeof(DataBaseTableAttribute), false))
            {
                foreach (var item in typeof(T).GetProperties())
                {
                    if (item.IsDefined(typeof(DataBaseMemberAttribute), false))
                    {
                        DataBaseMemberAttribute member = item.GetCustomAttributes(typeof(DataBaseMemberAttribute), false)[0] as DataBaseMemberAttribute;
                        //System.Linq.Expressions.Expression<Func<T, Object>> ex = x => typeof(T).InvokeMember(item.Name, BindingFlags.GetProperty, null, x, null);
                        //System.Linq.Expressions.ExpressionType.MemberAccess.Tostring();
                        this.Property(item.Name,//x => x.Null,//new Holder<T>(x, item).Property,
                            //(Int32)typeof(T).InvokeMember(item.Name, BindingFlags.GetProperty, null, x, null) ,
                            map =>
                            {
                                map.Type(GetNHibernateType(member.Type));
                                if (member.IsLazy)
                                {
                                    map.Lazy(true);
                                }
                                if (member.NotNullable)
                                {
                                    map.NotNullable(true);
                                }
                                if (member.Length > 0)
                                {
                                    map.Length(member.Length);
                                }
                            }
                        );
                    }
                }
            }
        }

        private IType GetNHibernateType(System.Type type)
        {
            if (type == typeof(DateTime))
            {
                return NHibernateUtil.DateTime;
            }
            else if (type == typeof(int))
            {
                return NHibernateUtil.Int32;
            }
            else if (type == typeof(long))
            {
                return NHibernateUtil.Int64;
            }
            else if (type == typeof(bool))
            {
                return NHibernateUtil.Boolean;
            }
            else if (type == typeof(double))
            {
                return NHibernateUtil.Double;
            }
            else if (type == typeof(float))
            {
                return NHibernateUtil.Double;
            }
            else if (type == typeof(Decimal))
            {
                return NHibernateUtil.Decimal;
            }
            else if (type == typeof(Guid))
            {
                return NHibernateUtil.Guid;
            }
            else
            {
                return NHibernateUtil.String;
            }
        }
    }
}
